'use strict';

exports.__esModule = true;

var _extends2 = require('babel-runtime/helpers/extends');

var _extends3 = _interopRequireDefault(_extends2);

var _objectWithoutProperties2 = require('babel-runtime/helpers/objectWithoutProperties');

var _objectWithoutProperties3 = _interopRequireDefault(_objectWithoutProperties2);

exports.default = promiseMiddleware;

var _normalizr = require('normalizr');

var _api = require('../libs/api');

var _api2 = _interopRequireDefault(_api);

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

var isPromise = function isPromise(val) {
  return val && typeof val.then === 'function';
};

function promiseMiddleware(_ref) {
  var dispatch = _ref.dispatch,
      getState = _ref.getState;

  return function (next) {
    return function (action) {
      var promise = action.promise,
          type = action.type,
          rest = (0, _objectWithoutProperties3.default)(action, ['promise', 'type']);
      var _rest$meta = rest.meta,
          meta = _rest$meta === undefined ? {} : _rest$meta;

      var schema = meta.schema;

      // Pass to next middleware or `dispatch` if there is no `promise` passed in
      if (!promise) {
        return next(action);
      }

      // We follow the strict naming conventions
      var REQUEST = type;
      var SUCCESS = REQUEST + '_SUCCESS';
      var FAILURE = REQUEST + '_FAILURE';

      // If `promise` is promise then use it
      // Else call it then it should return a promise object
      var actionPromise = isPromise(promise) ? promise : promise(dispatch, getState, _api2.default);

      /**
       * First, dispatch the `REQUEST` action.
       * Users could set the pending status for it
       */
      next((0, _extends3.default)({}, rest, { type: REQUEST }));

      function resolve(_ref2) {
        var payload = _ref2.payload;

        var finalPayload = payload;

        if (schema) {
          finalPayload = (0, _normalizr.normalize)(payload, schema);
        }

        if (meta && meta.normalize) {
          finalPayload = meta.normalize(payload, { dispatch: dispatch, getState: getState });
        }

        var resolvedAction = (0, _extends3.default)({}, rest, {
          type: SUCCESS,
          payload: finalPayload
        });

        dispatch(resolvedAction);

        return { payload: finalPayload, action: resolvedAction };
      }

      function reject(error) {
        var rejectedAction = (0, _extends3.default)({}, rest, {
          type: FAILURE,
          payload: error,
          error: true
        });

        dispatch(rejectedAction);

        throw error;
      }

      return actionPromise.then(resolve, reject);
    };
  };
}